﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace Chaow.Sample {
    public static class SourceReader {
        public static IEnumerable<string[]> Read(string path) {
            //File not found, exit
            if (!File.Exists(path))
                yield break;

            //Read sample file
            string content;
            using (StreamReader reader = File.OpenText(path)) {
                content = reader.ReadToEnd();
            }

            //Code for retrieve content
            string regContent = @"
                (                                       #any of
                    (?://.*)|                           #- single line comment
                    (?:/\*([^*]|\*(?!/))*\*/)|          #- multi line comment
                    [^{]                                #- any except open brace
                )*
                \{(?'content'(                          #start content any of
                    (?://.*\n)|                         #- single line comment
                    (?:/\*([^*]|\*(?!/))*\*/)|          #- multi line comment
                    (?:'[^']+')|                        #- char
                    (?:""([^""]|(?<=\\)"")*"")|         #- string
                    (?:@""([^""]|"""")*"")|             #- @string
                    (?'brace'\{)|                       #- open brace
                    (?(brace)                           #  * on brace open
                        ([^}]|(?'-brace'}))|            #    . match any char or close brace
                        [^}])                           #  * else match any except close brace
                )*(?(brace)(?!)))}                      #failed on brace is openned";
            
            //Match namespace
            Regex matchNS = new Regex(@"namespace\s+(?'namespace'[^\s/{]+)" + regContent,
                RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

            //Match class
            Regex matchCls = new Regex(@"public\s+(static\s+)?class\s+(?'class'[^\s/{]+)" + regContent,
                RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

            //Match method
            Regex matchMthd = new Regex(@"public\s+static\s+void\s+(?'method'[^\s(]+)\s*\(\s*\)" + regContent,
                RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

            //Decrease indent
            Regex decreaseInd = new Regex(@"(?'indent'\n[\t ]+)", RegexOptions.Compiled | RegexOptions.Multiline);

            //Read and match content
            string ns, cls, cnt;
            foreach (Match m in matchNS.Matches(content)) {
                ns = m.Groups["namespace"].Value;
                foreach (Match m2 in matchCls.Matches(m.Groups["content"].Value)) {
                    cls = m2.Groups["class"].Value;
                    foreach (Match m3 in matchMthd.Matches(m2.Groups["content"].Value)) {
                        cnt = m3.Groups["content"].Value;
                        cnt = cnt.Replace(decreaseInd.Match(cnt).Value, "\n").Replace("\r\n", "\n");
                        yield return new[] { ns, cls, m3.Groups["method"].Value, cnt };
                    }
                }
            }
        }
    }
}
